<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover">
    <meta name="format-detection" content="telephone=no">
    <style type="text/css">

#watermark {

  position: relative;
  overflow: hidden;
}

#watermark .x {
  position: absolute;
  top: 800;
  left: 400;
  color: #3300ff;
  font-size: 50px;
  pointer-events: none;
  opacity:0.3;
  filter:Alpha(opacity=50);
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
}
    </style>


    <style type="text/css">
 html{color:#333;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-rendering:optimizelegibility;font-family:Helvetica Neue,PingFang SC,Verdana,Microsoft Yahei,Hiragino Sans GB,Microsoft Sans Serif,WenQuanYi Micro Hei,sans-serif}html.borderbox *,html.borderbox :after,html.borderbox :before{box-sizing:border-box}article,aside,blockquote,body,button,code,dd,details,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hr,input,legend,li,menu,nav,ol,p,pre,section,td,textarea,th,ul{margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,menu,nav,section{display:block}audio,canvas,video{display:inline-block}body,button,input,select,textarea{font:300 1em/1.8 PingFang SC,Lantinghei SC,Microsoft Yahei,Hiragino Sans GB,Microsoft Sans Serif,WenQuanYi Micro Hei,Helvetica,sans-serif}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}blockquote{position:relative;color:#999;font-weight:400;border-left:1px solid #1abc9c;padding-left:1em;margin:1em 3em 1em 2em}@media only screen and (max-width:640px){blockquote{margin:1em 0}}abbr,acronym{border-bottom:1px dotted;font-variant:normal}abbr{cursor:help}del{text-decoration:line-through}address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:400}ol,ul{list-style:none}caption,th{text-align:left}q:after,q:before{content:""}sub,sup{font-size:75%;line-height:0;position:relative}:root sub,:root sup{vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}a{color:#1abc9c}a:hover{text-decoration:underline}.typo a{border-bottom:1px solid #1abc9c}.typo a:hover{border-bottom-color:#555;color:#555}.typo a:hover,a,ins{text-decoration:none}.typo-u,u{text-decoration:underline}mark{background:#fffdd1;border-bottom:1px solid #ffedce;padding:2px;margin:0 5px}code,pre,pre tt{font-family:Courier,Courier New,monospace}pre{background:hsla(0,0%,97%,.7);border:1px solid #ddd;padding:1em 1.5em;display:block;-webkit-overflow-scrolling:touch}hr{border:none;border-bottom:1px solid #cfcfcf;margin-bottom:.8em;height:10px}.typo-small,figcaption,small{font-size:.9em;color:#888}b,strong{font-weight:700;color:#000}[draggable]{cursor:move}.clearfix:after,.clearfix:before{content:"";display:table}.clearfix:after{clear:both}.clearfix{zoom:1}.textwrap,.textwrap td,.textwrap th{word-wrap:break-word;word-break:break-all}.textwrap-table{table-layout:fixed}.serif{font-family:Palatino,Optima,Georgia,serif}.typo-dl,.typo-form,.typo-hr,.typo-ol,.typo-p,.typo-pre,.typo-table,.typo-ul,.typo dl,.typo form,.typo hr,.typo ol,.typo p,.typo pre,.typo table,.typo ul,blockquote{margin-bottom:1rem}h1,h2,h3,h4,h5,h6{font-family:PingFang SC,Helvetica Neue,Verdana,Microsoft Yahei,Hiragino Sans GB,Microsoft Sans Serif,WenQuanYi Micro Hei,sans-serif;color:#000;line-height:1.35}.typo-h1,.typo-h2,.typo-h3,.typo-h4,.typo-h5,.typo-h6,.typo h1,.typo h2,.typo h3,.typo h4,.typo h5,.typo h6{margin-top:1.2em;margin-bottom:.6em;line-height:1.35}.typo-h1,.typo h1{font-size:2em}.typo-h2,.typo h2{font-size:1.8em}.typo-h3,.typo h3{font-size:1.6em}.typo-h4,.typo h4{font-size:1.4em}.typo-h5,.typo-h6,.typo h5,.typo h6{font-size:1.2em}.typo-ul,.typo ul{margin-left:1.3em;list-style:disc}.typo-ol,.typo ol{list-style:decimal;margin-left:1.9em}.typo-ol ol,.typo-ol ul,.typo-ul ol,.typo-ul ul,.typo li ol,.typo li ul{margin-bottom:.8em;margin-left:2em}.typo-ol ul,.typo-ul ul,.typo li ul{list-style:circle}.typo-table td,.typo-table th,.typo table caption,.typo table td,.typo table th{border:1px solid #ddd;padding:.5em 1em;color:#666}.typo-table th,.typo table th{background:#fbfbfb}.typo-table thead th,.typo table thead th{background:hsla(0,0%,95%,.7)}.typo table caption{border-bottom:none}.typo-input,.typo-textarea{-webkit-appearance:none;border-radius:0}.typo-em,.typo em,caption,legend{color:#000;font-weight:inherit}.typo-em{position:relative}.typo-em:after{position:absolute;top:.65em;left:0;width:100%;overflow:hidden;white-space:nowrap;content:"\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB"}.typo img{max-width:100%}.common-content{font-weight:400;color:#353535;line-height:1.75rem;white-space:normal;word-break:normal;font-size:1rem}.common-content img{display:block;max-width:100%;background-color:#eee}.common-content audio,.common-content video{width:100%;background-color:#eee}.common-content center,.common-content font{margin-top:1rem;display:inline-block}.common-content center{width:100%}.common-content pre{margin-top:1rem;padding-left:0;padding-right:0;position:relative;overflow:hidden}.common-content pre code{font-size:.8rem;font-family:Consolas,Liberation Mono,Menlo,monospace,Courier;display:block;width:100%;box-sizing:border-box;padding-left:1rem;padding-right:1rem;overflow-x:auto}.common-content hr{border:none;margin-top:1.5rem;margin-bottom:1.5rem;border-top:1px solid #f5f5f5;height:1px;background:none}.common-content b,.common-content h1,.common-content h2,.common-content h3,.common-content h4,.common-content h5,.common-content strong{font-weight:700}.common-content h1,.common-content h2{font-size:1.125rem;margin-bottom:.45rem}.common-content h3,.common-content h4,.common-content h5{font-size:1rem;margin-bottom:.45rem}.common-content p{font-weight:400;color:#353535;margin-top:.15rem}.common-content .orange{color:#ff5a05}.common-content .reference{font-size:1rem;color:#888}.custom-rich-content h1{margin-top:0;font-weight:400;font-size:15.25px;border-bottom:1px solid #eee;line-height:2.8}.custom-rich-content li,.custom-rich-content p{font-size:14px;color:#888;line-height:1.6}table.hljs-ln{margin-bottom:0;border-spacing:0;border-collapse:collapse}table.hljs-ln,table.hljs-ln tbody,table.hljs-ln td,table.hljs-ln tr{box-sizing:border-box}table.hljs-ln td{padding:0;border:0}table.hljs-ln td.hljs-ln-numbers{min-width:15px;color:rgba(27,31,35,.3);text-align:right;white-space:nowrap;cursor:pointer;user-select:none}table.hljs-ln td.hljs-ln-code,table.hljs-ln td.hljs-ln-numbers{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;font-size:12px;line-height:20px;vertical-align:top}table.hljs-ln td.hljs-ln-code{position:relative;padding-right:10px;padding-left:10px;overflow:visible;color:#24292e;word-wrap:normal;white-space:pre}video::-webkit-media-controls{overflow:hidden!important}video::-webkit-media-controls-enclosure{width:calc(100% + 32px);margin-left:auto}.button-cancel{color:#888;border:1px solid #888;border-radius:3px;margin-right:12px}.button-cancel,.button-primary{-ms-flex-positive:1;flex-grow:1;height:35px;display:inline-block;font-size:15px;text-align:center;line-height:36px}.button-primary{color:#fff;background-color:#ff5a05;border-radius:3px}@font-face{font-family:iconfont;src:url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.eot);src:url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.eot#iefix) format("embedded-opentype"),url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.woff) format("woff"),url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.ttf) format("truetype"),url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.svg#iconfont) format("svg")}@font-face{font-family:player-font;src:url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.eot);src:url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.eot#iefix) format("embedded-opentype"),url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.woff) format("woff"),url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.ttf) format("truetype"),url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.svg#player-font) format("svg")}.iconfont{font-family:iconfont!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-webkit-text-stroke-width:.2px;-moz-osx-font-smoothing:grayscale}html{background:#fff;min-height:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{width:100%}body.fixed{overflow:hidden;position:fixed;width:100vw;height:100vh}i{font-style:normal}a{word-wrap:break-word;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:hover{text-decoration:none}.fade-enter-active,.fade-leave-active{transition:opacity .3s}.fade-enter,.fade-leave-to{opacity:0}.MathJax,.MathJax_CHTML,.MathJax_MathContainer,.MathJax_MathML,.MathJax_PHTML,.MathJax_PlainSource,.MathJax_SVG{outline:0}.ios-app-switch .js-audit{display:none}._loading_wrap_{position:fixed;width:100vw;height:100vh;top:50%;left:50%;transform:translate(-50%,-50%);z-index:999}._loading_div_class_,._loading_wrap_{display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}._loading_div_class_{word-wrap:break-word;padding:.5rem .75rem;text-align:center;z-index:9999;font-size:.6rem;max-width:60%;color:#fff;border-radius:.25rem;-ms-flex-direction:column;flex-direction:column}._loading_div_class_ .message{color:#353535;font-size:16px;line-height:3}.spinner{animation:circle-rotator 1.4s linear infinite}.spinner *{line-height:0;box-sizing:border-box}@keyframes circle-rotator{0%{transform:rotate(0deg)}to{transform:rotate(270deg)}}.path{stroke-dasharray:187;stroke-dashoffset:0;transform-origin:center;animation:circle-dash 1.4s ease-in-out infinite,circle-colors 5.6s ease-in-out infinite}@keyframes circle-colors{0%{stroke:#ff5a05}to{stroke:#ff5a05}}@keyframes circle-dash{0%{stroke-dashoffset:187}50%{stroke-dashoffset:46.75;transform:rotate(135deg)}to{stroke-dashoffset:187;transform:rotate(450deg)}}.confirm-box-wrapper,.confirm-box-wrapper .mask{position:absolute;top:0;left:0;right:0;bottom:0}.confirm-box-wrapper .mask{background:rgba(0,0,0,.6)}.confirm-box-wrapper .confirm-box{position:fixed;top:50%;left:50%;width:267px;background:#fff;transform:translate(-50%,-50%);border-radius:7px}.confirm-box-wrapper .confirm-box .head{margin:0 18px;font-size:18px;text-align:center;line-height:65px;border-bottom:1px solid #d9d9d9}.confirm-box-wrapper .confirm-box .body{padding:18px;padding-bottom:0;color:#353535;font-size:12.5px;max-height:150px;overflow:auto}.confirm-box-wrapper .confirm-box .foot{display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;padding:18px}.confirm-box-wrapper .confirm-box .foot .button-cancel{border:1px solid #d9d9d9}.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}




    </style>
    <style type="text/css">
        .button-cancel[data-v-87ffcada]{color:#888;border:1px solid #888;border-radius:3px;margin-right:12px}.button-cancel[data-v-87ffcada],.button-primary[data-v-87ffcada]{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;height:35px;display:inline-block;font-size:15px;text-align:center;line-height:36px}.button-primary[data-v-87ffcada]{color:#fff;background-color:#ff5a05;border-radius:3px}.pd[data-v-87ffcada]{padding-left:1.375rem;padding-right:1.375rem}.article[data-v-87ffcada]{max-width:70rem;margin:0 auto}.article .article-unavailable[data-v-87ffcada]{color:#fa8919;font-size:15px;font-weight:600;line-height:24px;border-radius:5px;padding:12px;background-color:#f6f7fb;margin-top:20px}.article .article-unavailable .iconfont[data-v-87ffcada]{font-size:12px}.article .main[data-v-87ffcada]{padding:1.25rem 0;margin-bottom:52px}.article-title[data-v-87ffcada]{color:#353535;font-weight:400;line-height:1.65rem;font-size:1.34375rem}.article-info[data-v-87ffcada]{color:#888;font-size:.9375rem;margin-top:1.0625rem}.article-content[data-v-87ffcada]{margin-top:1.0625rem}.article-content.android video[data-v-87ffcada]::-webkit-media-controls-fullscreen-button{display:none}.copyright[data-v-87ffcada]{color:#b2b2b2;padding-bottom:20px;margin-top:20px;font-size:13px}.audio-player[data-v-87ffcada]{width:100%;margin:20px 0}.to-comment[data-v-87ffcada]{overflow:hidden;padding-top:10px;margin-bottom:-30px}.to-comment a.button-primary[data-v-87ffcada]{float:right;height:20px;font-size:12px;line-height:20px;padding:4px 8px;cursor:pointer}.article-comments[data-v-87ffcada]{margin-top:2rem}.article-comments h2[data-v-87ffcada]{text-align:center;color:#888;position:relative;z-index:1;margin-bottom:1rem}.article-comments h2[data-v-87ffcada]:before{border-top:1px dotted #888;content:"";position:absolute;top:56%;left:0;width:100%;z-index:-1}.article-comments h2 span[data-v-87ffcada]{font-size:15.25px;font-weight:400;padding:0 1rem;background:#fff;display:inline-block}.article-sub-bottom[data-v-87ffcada]{z-index:10;cursor:pointer}.switch-btns[data-v-87ffcada]{height:76px;cursor:pointer;padding-top:24px;padding-bottom:24px;border-bottom:10px solid #f6f7fb;position:relative}.switch-btns[data-v-87ffcada]:before{content:" ";height:1px;background:#e8e8e8;position:absolute;top:0;left:0;-webkit-box-sizing:border-box;box-sizing:border-box;left:1.375rem;right:1.375rem}.switch-btns .btn[data-v-87ffcada]{height:38px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.switch-btns .btn .tag[data-v-87ffcada]{-webkit-box-flex:0;-ms-flex:0 0 62px;flex:0 0 62px;text-align:center;color:#888;font-size:14px;border-radius:10px;height:22px;line-height:22px;background:#f6f7fb;font-weight:400}.switch-btns .btn .txt[data-v-87ffcada]{margin-left:10px;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;color:#888;font-size:15px;height:22px;line-height:22px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400}@media (max-width:769px){.article .breadcrumb[data-v-87ffcada]{padding-top:10px;padding-bottom:10px}}





    </style>

    <style type="text/css">
        .comment-item{list-style-position:inside;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;margin-bottom:1rem}.comment-item a{border-bottom:none}.comment-item .avatar{width:2.625rem;height:2.625rem;-ms-flex-negative:0;flex-shrink:0;border-radius:50%}.comment-item .info{margin-left:.5rem;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.comment-item .info .hd{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.comment-item .info .hd .username{color:#888;font-size:15.25px;font-weight:400;line-height:1.2}.comment-item .info .hd .control{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.comment-item .info .hd .control .btn-share{color:#888;font-size:.75rem;margin-right:1rem}.comment-item .info .hd .control .btn-praise{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:15.25px;text-decoration:none}.comment-item .info .hd .control .btn-praise i{color:#888;display:inline-block;font-size:.75rem;margin-right:.3rem;margin-top:-.01rem}.comment-item .info .hd .control .btn-praise i.on,.comment-item .info .hd .control .btn-praise span{color:#ff5a05}.comment-item .info .bd{color:#353535;font-size:15.25px;font-weight:400;white-space:normal;word-break:break-all;line-height:1.6}.comment-item .info .time{color:#888;font-size:9px;line-height:1}.comment-item .info .reply .reply-hd{font-size:15.25px}.comment-item .info .reply .reply-hd span{margin-left:-12px;color:#888;font-weight:400}.comment-item .info .reply .reply-hd i{color:#ff5a05;font-size:15.25px}.comment-item .info .reply .reply-content{color:#353535;font-size:15.25px;font-weight:400;white-space:normal;word-break:break-all}.comment-item .info .reply .reply-time{color:#888;font-size:9px}




    </style>
</head>
<body>
<div id="app">


    <div data-v-87ffcada="" class="article" id="watermark">
        <p class="x">更多课程请加QQ群170701297</p>
        <div data-v-87ffcada="" class="main main-app">
            <h1 data-v-87ffcada="" class="article-title pd">
                18讲案例篇：内存泄漏了，我该如何定位和处理
            </h1>
            <div data-v-87ffcada="" class="article-content typo common-content pd"><img data-v-87ffcada=""
                                                                                        src="https://static001.geekbang.org/resource/image/15/d3/156ed307b9430f85095d18269e4084d3.jpg">


                <div data-v-87ffcada="" id="article-content" class="">
                    <div class="text">
                        <p>你好，我是倪朋飞。</p><p>通过前几节对内存基础的学习，我相信你对 Linux 内存的工作原理，已经有了初步了解。</p><p>对普通进程来说，能看到的其实是内核提供的虚拟内存，这些虚拟内存还需要通过页表，由系统映射为物理内存。</p><p>当进程通过 malloc() 申请虚拟内存后，系统并不会立即为其分配物理内存，而是在首次访问时，才通过缺页异常陷入内核中分配内存。</p><p>为了协调 CPU 与磁盘间的性能差异，Linux 还会使用 Cache 和 Buffer ，分别把文件和磁盘读写的数据缓存到内存中。</p><p>对应用程序来说，动态内存的分配和回收，是既核心又复杂的一个逻辑功能模块。管理内存的过程中，也很容易发生各种各样的“事故”，比如，</p><ul>
<li>
<p>没正确回收分配后的内存，导致了泄漏。</p>
</li>
<li>
<p>访问的是已分配内存边界外的地址，导致程序异常退出，等等。</p>
</li>
</ul><p>今天我就带你来看看，内存泄漏到底是怎么发生的，以及发生内存泄漏之后该如何排查和定位。</p><p>说起内存泄漏，这就要先从内存的分配和回收说起了。</p><h2>内存的分配和回收</h2><p>先回顾一下，你还记得应用程序中，都有哪些方法来分配内存吗？用完后，又该怎么释放还给系统呢？</p><p>前面讲进程的内存空间时，我曾经提到过，用户空间内存包括多个不同的内存段，比如只读段、数据段、堆、栈以及文件映射段等。这些内存段正是应用程序使用内存的基本方式。</p><!-- [[[read_end]]] --><p>举个例子，你在程序中定义了一个局部变量，比如一个整数数组 <em>int data[64]</em>  ，就定义了一个可以存储 64 个整数的内存段。由于这是一个局部变量，它会从内存空间的栈中分配内存。</p><p>栈内存由系统自动分配和管理。一旦程序运行超出了这个局部变量的作用域，栈内存就会被系统自动回收，所以不会产生内存泄漏的问题。</p><p>再比如，很多时候，我们事先并不知道数据大小，所以你就要用到标准库函数 <em>malloc()</em> _，_在程序中动态分配内存。这时候，系统就会从内存空间的堆中分配内存。</p><p>堆内存由应用程序自己来分配和管理。除非程序退出，这些堆内存并不会被系统自动释放，而是需要应用程序明确调用库函数 <em>free()</em> 来释放它们。如果应用程序没有正确释放堆内存，就会造成内存泄漏。</p><p>这是两个栈和堆的例子，那么，其他内存段是否也会导致内存泄漏呢？经过我们前面的学习，这个问题并不难回答。</p><ul>
<li>
<p>只读段，包括程序的代码和常量，由于是只读的，不会再去分配新的内存，所以也不会产生内存泄漏。</p>
</li>
<li>
<p>数据段，包括全局变量和静态变量，这些变量在定义时就已经确定了大小，所以也不会产生内存泄漏。</p>
</li>
<li>
<p>最后一个内存映射段，包括动态链接库和共享内存，其中共享内存由程序动态分配和管理。所以，如果程序在分配后忘了回收，就会导致跟堆内存类似的泄漏问题。</p>
</li>
</ul><p><strong>内存泄漏的危害非常大，这些忘记释放的内存，不仅应用程序自己不能访问，系统也不能把它们再次分配给其他应用</strong>。内存泄漏不断累积，甚至会耗尽系统内存。</p><p>虽然，系统最终可以通过 OOM （Out of Memory）机制杀死进程，但进程在 OOM 前，可能已经引发了一连串的反应，导致严重的性能问题。</p><p>比如，其他需要内存的进程，可能无法分配新的内存；内存不足，又会触发系统的缓存回收以及 SWAP 机制，从而进一步导致 I/O 的性能问题等等。</p><p>内存泄漏的危害这么大，那我们应该怎么检测这种问题呢？特别是，如果你已经发现了内存泄漏，该如何定位和处理呢。</p><p>接下来，我们就用一个计算斐波那契数列的案例，来看看内存泄漏问题的定位和处理方法。</p><p>斐波那契数列是一个这样的数列：0、1、1、2、3、5、8...，也就是除了前两个数是0和1，其他数都由前面两数相加得到，用数学公式来表示就是 F(n)=F(n-1)+F(n-2)，（n&gt;=2），F(0)=0, F(1)=1。</p><h2>案例</h2><p>今天的案例基于 Ubuntu 18.04，当然，同样适用其他的 Linux 系统。</p><ul>
<li>
<p>机器配置：2 CPU，8GB 内存</p>
</li>
<li>
<p>预先安装 sysstat、Docker 以及 bcc 软件包，比如：</p>
</li>
</ul><pre><code># install sysstat docker
sudo apt-get install -y sysstat docker.io

# Install bcc
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4052245BD4284CDD
echo &quot;deb https://repo.iovisor.org/apt/bionic bionic main&quot; | sudo tee /etc/apt/sources.list.d/iovisor.list
sudo apt-get update
sudo apt-get install -y bcc-tools libbcc-examples linux-headers-$(uname -r)
</code></pre><p>其中，sysstat 和 Docker 我们已经很熟悉了。sysstat 软件包中的 vmstat ，可以观察内存的变化情况；而 Docker 可以运行案例程序。</p><p><a href="https://github.com/iovisor/bcc">bcc</a> 软件包前面也介绍过，它提供了一系列的 Linux 性能分析工具，常用来动态追踪进程和内核的行为。更多工作原理你先不用深究，后面学习我们会逐步接触。这里你只需要记住，按照上面步骤安装完后，它提供的所有工具都位于 /usr/share/bcc/tools 这个目录中。</p><blockquote>
<p>注意：bcc-tools需要内核版本为4.1或者更高，如果你使用的是CentOS7，或者其他内核版本比较旧的系统，那么你需要手动<a href="https://github.com/iovisor/bcc/issues/462">升级内核版本后再安装</a>。</p>
</blockquote><p>打开一个终端，SSH 登录到机器上，安装上述工具。</p><p>同以前的案例一样，下面的所有命令都默认以 root 用户运行，如果你是用普通用户身份登陆系统，请运行 sudo su root 命令切换到 root 用户。</p><p>如果安装过程中有什么问题，同样鼓励你先自己搜索解决，解决不了的，可以在留言区向我提问。如果你以前已经安装过了，就可以忽略这一点了。</p><p>安装完成后，再执行下面的命令来运行案例：</p><pre><code>$ docker run --name=app -itd feisky/app:mem-leak
</code></pre><p>案例成功运行后，你需要输入下面的命令，确认案例应用已经正常启动。如果一切正常，你应该可以看到下面这个界面：</p><pre><code>$ docker logs app
2th =&gt; 1
3th =&gt; 2
4th =&gt; 3
5th =&gt; 5
6th =&gt; 8
7th =&gt; 13
</code></pre><p>从输出中，我们可以发现，这个案例会输出斐波那契数列的一系列数值。实际上，这些数值每隔 1 秒输出一次。</p><p>知道了这些，我们应该怎么检查内存情况，判断有没有泄漏发生呢？你首先想到的可能是 top 工具，不过，top 虽然能观察系统和进程的内存占用情况，但今天的案例并不适合。内存泄漏问题，我们更应该关注内存使用的变化趋势。</p><p>所以，开头我也提到了，今天推荐的是另一个老熟人， vmstat 工具。</p><p>运行下面的 vmstat ，等待一段时间，观察内存的变化情况。如果忘了 vmstat 里各指标的含义，记得复习前面内容，或者执行 man vmstat 查询。</p><pre><code># 每隔3秒输出一组数据
$ vmstat 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
0  0      0 6601824  97620 1098784    0    0     0     0   62  322  0  0 100  0  0
0  0      0 6601700  97620 1098788    0    0     0     0   57  251  0  0 100  0  0
0  0      0 6601320  97620 1098788    0    0     0     3   52  306  0  0 100  0  0
0  0      0 6601452  97628 1098788    0    0     0    27   63  326  0  0 100  0  0
2  0      0 6601328  97628 1098788    0    0     0    44   52  299  0  0 100  0  0
0  0      0 6601080  97628 1098792    0    0     0     0   56  285  0  0 100  0  0 
</code></pre><p>从输出中你可以看到，内存的 free 列在不停的变化，并且是下降趋势；而 buffer 和 cache 基本保持不变。</p><p>未使用内存在逐渐减小，而 buffer 和 cache 基本不变，这说明，系统中使用的内存一直在升高。但这并不能说明有内存泄漏，因为应用程序运行中需要的内存也可能会增大。比如说，程序中如果用了一个动态增长的数组来缓存计算结果，占用内存自然会增长。</p><p>那怎么确定是不是内存泄漏呢？或者换句话说，有没有简单方法找出让内存增长的进程，并定位增长内存用在哪儿呢？</p><p>根据前面内容，你应该想到了用 top 或ps 来观察进程的内存使用情况，然后找出内存使用一直增长的进程，最后再通过 pmap 查看进程的内存分布。</p><p>但这种方法并不太好用，因为要判断内存的变化情况，还需要你写一个脚本，来处理 top 或者 ps 的输出。</p><p>这里，我介绍一个专门用来检测内存泄漏的工具，memleak。memleak 可以跟踪系统或指定进程的内存分配、释放请求，然后定期输出一个未释放内存和相应调用栈的汇总情况（默认5 秒）。</p><p>当然，memleak 是 bcc 软件包中的一个工具，我们一开始就装好了，执行 <em>/usr/share/bcc/tools/memleak</em> 就可以运行它。比如，我们运行下面的命令：</p><pre><code># -a 表示显示每个内存分配请求的大小以及地址
# -p 指定案例应用的PID号
$ /usr/share/bcc/tools/memleak -a -p $(pidof app)
WARNING: Couldn't find .text section in /app
WARNING: BCC can't handle sym look ups for /app
    addr = 7f8f704732b0 size = 8192
    addr = 7f8f704772d0 size = 8192
    addr = 7f8f704712a0 size = 8192
    addr = 7f8f704752c0 size = 8192
    32768 bytes in 4 allocations from stack
        [unknown] [app]
        [unknown] [app]
        start_thread+0xdb [libpthread-2.27.so] 
</code></pre><p>从 memleak 的输出可以看到，案例应用在不停地分配内存，并且这些分配的地址没有被回收。</p><p>这里有一个问题，Couldn’t find .text section in /app，所以调用栈不能正常输出，最后的调用栈部分只能看到 [unknown] 的标志。</p><p>为什么会有这个错误呢？实际上，这是由于案例应用运行在容器中导致的。memleak 工具运行在容器之外，并不能直接访问进程路径 /app。</p><p>比方说，在终端中直接运行 ls 命令，你会发现，这个路径的确不存在：</p><pre><code>$ ls /app
ls: cannot access '/app': No such file or directory
</code></pre><p>类似的问题，我在 CPU 模块中的 <a href="https://time.geekbang.org/column/article/73738">perf 使用方法</a>中已经提到好几个解决思路。最简单的方法，就是在容器外部构建相同路径的文件以及依赖库。这个案例只有一个二进制文件，所以只要把案例应用的二进制文件放到 /app 路径中，就可以修复这个问题。</p><p>比如，你可以运行下面的命令，把 app 二进制文件从容器中复制出来，然后重新运行 memleak 工具：</p><pre><code>$ docker cp app:/app /app
$ /usr/share/bcc/tools/memleak -p $(pidof app) -a
Attaching to pid 12512, Ctrl+C to quit.
[03:00:41] Top 10 stacks with outstanding allocations:
    addr = 7f8f70863220 size = 8192
    addr = 7f8f70861210 size = 8192
    addr = 7f8f7085b1e0 size = 8192
    addr = 7f8f7085f200 size = 8192
    addr = 7f8f7085d1f0 size = 8192
    40960 bytes in 5 allocations from stack
        fibonacci+0x1f [app]
        child+0x4f [app]
        start_thread+0xdb [libpthread-2.27.so] 
</code></pre><p>这一次，我们终于看到了内存分配的调用栈，原来是 fibonacci() 函数分配的内存没释放。</p><p>定位了内存泄漏的来源，下一步自然就应该查看源码，想办法修复它。我们一起来看案例应用的源代码 <a href="https://github.com/feiskyer/linux-perf-examples/blob/master/mem-leak/app.c">app.c</a>：</p><pre><code>$ docker exec app cat /app.c
\.\.\.
long long *fibonacci(long long *n0, long long *n1)
{
    //分配1024个长整数空间方便观测内存的变化情况
    long long *v = (long long *) calloc(1024, sizeof(long long));
    *v = *n0 + *n1;
    return v;
}


void *child(void *arg)
{
    long long n0 = 0;
    long long n1 = 1;
    long long *v = NULL;
    for (int n = 2; n &gt; 0; n++) {
        v = fibonacci(&amp;n0, &amp;n1);
        n0 = n1;
        n1 = *v;
        printf(&quot;%dth =&gt; %lld\n&quot;, n, *v);
        sleep(1);
    }
}
\.\.\. 
</code></pre><p>你会发现， child() 调用了 fibonacci() 函数，但并没有释放 fibonacci() 返回的内存。所以，想要修复泄漏问题，在 child() 中加一个释放函数就可以了，比如：</p><pre><code>void *child(void *arg)
{
    \.\.\.
    for (int n = 2; n &gt; 0; n++) {
        v = fibonacci(&amp;n0, &amp;n1);
        n0 = n1;
        n1 = *v;
        free(v);    // 释放内存
        printf(&quot;%dth =&gt; %lld\n&quot;, n, *v);
        sleep(1);
    }
} 
</code></pre><p>我把修复后的代码放到了 <a href="https://github.com/feiskyer/linux-perf-examples/blob/master/mem-leak/app-fix.c">app-fix.c</a>，也打包成了一个 Docker 镜像。你可以运行下面的命令，验证一下内存泄漏是否修复：</p><pre><code># 清理原来的案例应用
$ docker rm -f app

# 运行修复后的应用
$ docker run --name=app -itd feisky/app:mem-leak-fix

# 重新执行 memleak工具检查内存泄漏情况
$ /usr/share/bcc/tools/memleak -a -p $(pidof app)
Attaching to pid 18808, Ctrl+C to quit.
[10:23:18] Top 10 stacks with outstanding allocations:
[10:23:23] Top 10 stacks with outstanding allocations:
</code></pre><p>现在，我们看到，案例应用已经没有遗留内存，证明我们的修复工作成功完成。</p><h2>小结</h2><p>总结一下今天的内容。</p><p>应用程序可以访问的用户内存空间，由只读段、数据段、堆、栈以及文件映射段等组成。其中，堆内存和内存映射，需要应用程序来动态管理内存段，所以我们必须小心处理。不仅要会用标准库函数 <em>malloc()</em>  来动态分配内存，还要记得在用完内存后，调用库函数 _free() 来_释放它们。</p><p>今天的案例比较简单，只用加一个 <em>free()</em> 调用就能修复内存泄漏。不过，实际应用程序就复杂多了。比如说，</p><ul>
<li>
<p>malloc() 和 free() 通常并不是成对出现，而是需要你，在每个异常处理路径和成功路径上都释放内存 。</p>
</li>
<li>
<p>在多线程程序中，一个线程中分配的内存，可能会在另一个线程中访问和释放。</p>
</li>
<li>
<p>更复杂的是，在第三方的库函数中，隐式分配的内存可能需要应用程序显式释放。</p>
</li>
</ul><p>所以，为了避免内存泄漏，最重要的一点就是养成良好的编程习惯，比如分配内存后，一定要先写好内存释放的代码，再去开发其他逻辑。还是那句话，有借有还，才能高效运转，再借不难。</p><p>当然，如果已经完成了开发任务，你还可以用 memleak 工具，检查应用程序的运行中，内存是否泄漏。如果发现了内存泄漏情况，再根据 memleak 输出的应用程序调用栈，定位内存的分配位置，从而释放不再访问的内存。</p><h2>思考</h2><p>最后，给你留一个思考题。</p><p>今天的案例，我们通过增加 <em>free()</em> 调用，释放函数 <em>fibonacci()</em> 分配的内存，修复了内存泄漏的问题。就这个案例而言，还有没有其他更好的修复方法呢？结合前面学习和你自己的工作经验，相信你一定能有更多更好的方案。</p><p>欢迎留言和我讨论 ，写下你的答案和收获，也欢迎你把这篇文章分享给你的同事、朋友。我们一起在实战中演练，在交流中进步。</p><p><img src="https://static001.geekbang.org/resource/image/a3/e9/a396aed4116c2c989771c1295736abe9.jpg" alt=""></p>
                    </div>
                </div>

            </div>
            <div data-v-87ffcada="" class="article-comments pd"><h2 data-v-87ffcada=""><span
                    data-v-87ffcada="">精选留言</span></h2>
                <ul data-v-87ffcada="">
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/0f/7c/10/165cb374.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">Scott</span>
                            </div>
                            <div class="bd">我比较关心老版本的Linux怎么做同样的事，毕竟没有办法升级公司服务器的内核。 <br></div>
                            <span class="time">2019-01-01 20:32</span>
                            
                            <div class="reply">
                                <div class="reply-hd"><span>作者回复</span></div>
                                <p class="reply-content">另一个用的比较多的是valgrind</p>
                                <p class="reply-time">2019-01-02 18:23</p>
                            </div>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/14/0c/ca/6173350b.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">郭江伟</span>
                            </div>
                            <div class="bd">本例中将动态分配内存改为使用数组，然后就不需要自己free了；<br>将app.c拷贝为app2.c  做如下修改，因为篇幅有限没法贴完全代码：<br>long long fibonacci(long long *n0, long long *n1)<br>{<br>	&#47;&#47;分配1024个长整数空间方便观测内存的变化情况<br>&#47;&#47;	long long *v = (long long *) calloc(1024, sizeof(long long));<br>         long long v[1024];<br>然后执行memleak<br>gjw@gjw:~$ sudo &#47;usr&#47;share&#47;bcc&#47;tools&#47;memleak  -p $(pidof app2c)<br>Attaching to pid 3463, Ctrl+C to quit.<br>[13:02:24] Top 10 stacks with outstanding allocations:<br>[13:02:29] Top 10 stacks with outstanding allocations:<br>^Cgjw@gjw:~$ sudo &#47;usr&#47;share&#47;bcc&#47;tools&#47;memleak  -p $(pidof app2c)<br>Attaching to pid 3463, Ctrl+C to quit.<br>[13:02:43] Top 10 stacks with outstanding allocations:<br>[13:02:48] Top 10 stacks with outstanding allocations:<br>[13:02:53] Top 10 stacks with outstanding allocations:<br>[13:02:58] Top 10 stacks with outstanding allocations:<br> <br></div>
                            <span class="time">2018-12-31 13:05</span>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/0f/57/ed/d96acbd7.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">mj4ever</span>
                            </div>
                            <div class="bd">老师：<br>遇到了个问题，google也查不出所以然：<br>1、ubuntu 18.04，内核4.15.0-29-generic<br>2、运行 memleak -a -p $(pidof app)，报错：<br>Attaching to pid 14069, Ctrl+C to quit.<br>perf_event_open(&#47;sys&#47;kernel&#47;debug&#47;tracing&#47;events&#47;uprobes&#47;p__lib_x86_64_linux_gnu_libc_2_27_so_0x97070_14069_bcc_14199&#47;id): Input&#47;output error<br>Traceback (most recent call last):<br>  File &quot;&#47;usr&#47;share&#47;bcc&#47;tools&#47;memleak&quot;, line 416, in &lt;module&gt;<br>    attach_probes(&quot;malloc&quot;)<br>  File &quot;&#47;usr&#47;share&#47;bcc&#47;tools&#47;memleak&quot;, line 406, in attach_probes<br>    pid=pid)<br>  File &quot;&#47;usr&#47;lib&#47;python2.7&#47;dist-packages&#47;bcc&#47;__init__.py&quot;, line 952, in attach_uprobe<br>    raise Exception(&quot;Failed to attach BPF to uprobe&quot;)<br>Exception: Failed to attach BPF to uprobe <br></div>
                            <span class="time">2019-01-01 15:21</span>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/12/64/05/6989dce6.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">我来也</span>
                            </div>
                            <div class="bd">[D18打卡]<br>想不到又有神器可以直接分析出是哪个函数导致了内存泄露。<br>以前都是在申请和释放的地方加标记，然后用工具去分析。<br>思考题：<br>一般能预分配的空间都没必要去动态申请。<br>这个案例可以把存放结果的值先定义好，函数参数中用指针过去，这样就没必要申请内存了。<br> <br></div>
                            <span class="time">2018-12-31 15:39</span>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">阿西吧</span>
                            </div>
                            <div class="bd">老师，你这个例子是已经知道哪个进程有内存泄露了，请问如何找出哪个进程呢？ <br></div>
                            <span class="time">2019-01-04 16:45</span>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/14/0f/84/d8e63885.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">仲鬼</span>
                            </div>
                            <div class="bd">老师好，之前哪节课讲过pmap？并没有找到 <br></div>
                            <span class="time">2019-01-04 15:47</span>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/13/57/6e/dd0eee5f.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">夜空中最亮的星（华仔）</span>
                            </div>
                            <div class="bd">老师，代码段里面可否把  代码前面的 $ 或 # 号，去掉。带着还的手动去掉下才能执行代码 <br></div>
                            <span class="time">2019-01-02 15:38</span>
                            
                            <div class="reply">
                                <div class="reply-hd"><span>作者回复</span></div>
                                <p class="reply-content">还是需要留着，去掉就不容易区分注释、命令和输出了</p>
                                <p class="reply-time">2019-01-03 00:08</p>
                            </div>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">划时代</span>
                            </div>
                            <div class="bd">memleak好像要比valgrind进行内存泄漏检测要方便很多。 <br></div>
                            <span class="time">2019-01-02 09:59</span>
                            
                            <div class="reply">
                                <div class="reply-hd"><span>作者回复</span></div>
                                <p class="reply-content">是的</p>
                                <p class="reply-time">2019-01-02 18:12</p>
                            </div>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="http://thirdwx.qlogo.cn/mmopen/vi_32/8OPzdpDraQMvCNWAicicDt54sDaIYJZicBLfMyibXVs4V0ZibEdkZlbzxxL7aGpRoeyvibag5LaAaaGKSdwYQMY2hUrQ/132" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">code2</span>
                            </div>
                            <div class="bd">防止内存泄露，在c中最好让malloc和free成对出现，不要在函数中分配，在函数外释放，这样一不留神就忘了，检查时也不容易发现。也可使用一些源代码内存泄露检测工具。在C++中除了成对出现外还要注意new和delete使用的一些要点。曾遇到过一个投资数千万的大项目，java做的，因内存泄露不能查明原因，服务器不得不每月杀掉服务进程，重新启动。 <br></div>
                            <span class="time">2019-01-01 09:21</span>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/10/7a/08/4d3e47dd.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">Aaron Cheung</span>
                            </div>
                            <div class="bd">坚持初衷，死磕就行，不退缩，不放弃！ <br></div>
                            <span class="time">2018-12-31 15:02</span>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="http://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eqvaPTSYCtlXUc9DZxe6MWHeRJEKEr9fNPXMveWtia4Kic3BOicwCuRK6SVKymvvw9PZ5unxiaSukvSXQ/132" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">萧董</span>
                            </div>
                            <div class="bd">memleak输出中一直有addr就是内存没有释放吗 <br></div>
                            <span class="time">2018-12-31 10:55</span>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/10/1b/36/abe6d066.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">付盼星</span>
                            </div>
                            <div class="bd">老师好，我有个问题想请教下，这里的堆栈和java虚拟机的堆栈是对应起来的么？ <br></div>
                            <span class="time">2018-12-31 09:19</span>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">dexter</span>
                            </div>
                            <div class="bd">1,如何判断目前系统环境是否已经发生了内存泄露<br>2,如何判断是哪个进程发生了内存泄露 <br></div>
                            <span class="time">2019-01-06 19:30</span>
                            
                            <div class="reply">
                                <div class="reply-hd"><span>作者回复</span></div>
                                <p class="reply-content">嗯，系统级的内存泄漏一个memleak就可以</p>
                                <p class="reply-time">2019-01-07 17:48</p>
                            </div>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">腾达</span>
                            </div>
                            <div class="bd">问一下，memleak这个程序用了一个线程来演示问题，这个有什么讲究吗？是不是故意为之？ <br></div>
                            <span class="time">2019-01-06 15:43</span>
                            
                            <div class="reply">
                                <div class="reply-hd"><span>作者回复</span></div>
                                <p class="reply-content">没有讲究，只是个案例，用不用线程都没关系</p>
                                <p class="reply-time">2019-01-07 17:51</p>
                            </div>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">noma</span>
                            </div>
                            <div class="bd">ubuntu <br>linux kernel: 4.4.0-21-generic<br>执行memleak也报错：<br>virtual&#47;main.c:18:1: error: could not open bpf map: Invalid argument<br>is maps&#47;stacktrace map type enabled in your kernel?<br>BPF_STACK_TRACE(stack_traces, 10240);<br>^<br>&#47;virtual&#47;include&#47;bcc&#47;helpers.h:199:3: note: expanded from macro &#39;BPF_STACK_TRACE&#39;<br>  BPF_TABLE(&quot;stacktrace&quot;, int, struct bpf_stacktrace, _name, roundup_pow_of_two(_max_entries))<br>  ^<br>&#47;virtual&#47;include&#47;bcc&#47;helpers.h:60:76: note: expanded from macro &#39;BPF_TABLE&#39;<br>#define BPF_TABLE(_table_type, _key_type, _leaf_type, _name, _max_entries) \<br>                                                                           ^<br>&#47;virtual&#47;include&#47;bcc&#47;helpers.h:56:4: note: expanded from macro &#39;\<br>BPF_F_TABLE&#39;<br>}; \<br>   ^<br>&#47;virtual&#47;main.c:83:25: error: bpf_table stack_traces failed to open<br>        info.stack_id = stack_traces.get_stackid(ctx, BPF_F_REUSE_STACKID|BPF_F_USER_STACK);<br>                        ^<br>2 errors generated.<br>Traceback (most recent call last):<br>  File &quot;&#47;usr&#47;share&#47;bcc&#47;tools&#47;memleak&quot;, line 394, in &lt;module&gt;<br>    bpf = BPF(text=bpf_source)<br>  File &quot;&#47;usr&#47;lib&#47;python2.7&#47;dist-packages&#47;bcc&#47;__init__.py&quot;, line 318, in __init__<br>    raise Exception(&quot;Failed to compile BPF text&quot;)<br>Exception: Failed to compile BPF text<br><br>看这个blog作者的回复：<br>http:&#47;&#47;blogs.microsoft.co.il&#47;sasha&#47;2016&#47;02&#47;14&#47;two-new-ebpf-tools-memleak-and-argdist&#47;<br><br>意思应该是现在的memleak版本需要内核支持 BPF stack trace，4.6版本的内核应该可以。然后在4.4版本的内核上，在&#47;usr&#47;share&#47;bcc&#47;tools&#47;old&#47;memleak应该能work, 嗯，我试了还是报同样的错误:( <br></div>
                            <span class="time">2019-01-05 23:33</span>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/14/d6/9e/27c476e1.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">梦舟</span>
                            </div>
                            <div class="bd">非常不错 <br></div>
                            <span class="time">2019-01-04 21:28</span>
                            
                            <div class="reply">
                                <div class="reply-hd"><span>作者回复</span></div>
                                <p class="reply-content">👍</p>
                                <p class="reply-time">2019-01-04 22:30</p>
                            </div>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="http://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLdWHFCr66TzHS2CpCkiaRaDIk3tU5sKPry16Q7ic0mZZdy8LOCYc38wOmyv5RZico7icBVeaPX8X2jcw/132" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">JohnT3e</span>
                            </div>
                            <div class="bd">思考题：fibonacci函数直接返回值，或者在child函数中分配局部变量v，fibonacci函数增加一个参数，传入局部变量v的地址。 <br></div>
                            <span class="time">2019-01-04 09:22</span>
                            
                            <div class="reply">
                                <div class="reply-hd"><span>作者回复</span></div>
                                <p class="reply-content">嗯，内置类型没必要去分配动态内存</p>
                                <p class="reply-time">2019-01-10 20:59</p>
                            </div>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/10/13/2d/ad1bfe92.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">江湖中人</span>
                            </div>
                            <div class="bd">有个疑问请教下：<br>for (int n = 2; n &gt; 0; n++) {<br>        v = fibonacci(&amp;n0, &amp;n1);<br>        n0 = n1;<br>        n1 = *v;<br>        free(v);    &#47;&#47; 释放内存<br>        printf(&quot;%dth =&gt; %lld\n&quot;, n, *v);<br>        sleep(1);<br>    }<br>这段代码中，在free(v)之後，printf中仍用到了v中存储的数据，不会有问题吗 <br></div>
                            <span class="time">2019-01-03 22:51</span>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/10/d9/47/86872313.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">holen</span>
                            </div>
                            <div class="bd">老师， 有没有 centos 下不用升级内核就可以检测内存的工具，像 valgrind 工具没办法指定 pid 检测,   有没有更好的工具推荐下呢 <br></div>
                            <span class="time">2019-01-03 10:46</span>
                            
                            <div class="reply">
                                <div class="reply-hd"><span>作者回复</span></div>
                                <p class="reply-content">据我所知，bcc这套工具是最好用的，其他的工具都有很多限制（比如不好用，或者收费）</p>
                                <p class="reply-time">2019-01-10 20:32</p>
                            </div>
                            
                        </div>
                    </li>
                    
                    <li data-v-87ffcada="" class="comment-item"><img
                            src="https://static001.geekbang.org/account/avatar/00/0f/ea/8b/613c162e.jpg" class="avatar">
                        <div class="info">
                            <div class="hd"><span class="username">nomoshen</span>
                            </div>
                            <div class="bd">目前我司用的内核版本还是2.6的；而且用valgrind会对线上正在执行的程序有很大性能影响吧；对内存泄露这块还是很难把握的；希望老师能x细聊这块 <br></div>
                            <span class="time">2019-01-03 09:38</span>
                            
                            <div class="reply">
                                <div class="reply-hd"><span>作者回复</span></div>
                                <p class="reply-content">valgrind不能指定PID分析，所以一般是通过监控系统发现有内存问题后，到线下用 valgrind 分析。</p>
                                <p class="reply-time">2019-01-10 20:30</p>
                            </div>
                            
                        </div>
                    </li>
                    


                </ul>
            </div>
        </div>
    </div>
</div>
</body>
</html>